#include "OverUnderVoltage.h"
#include "../function_interface.h"
#include "../types.h"
#include <stdio.h>
#include "../logInterface.h"
#include "../global_variable.h"

#if 1

typedef struct {
    int   olThrEnterVoltage_1v;//进入判定阈值
    int   olThrEnterTime_1s;//进入判定时间
    int   olThrExitVoltage_1v;//退出判定阈值
    int   olThrExitTime_1s;//退出判定时间
}ouVoltageConfType;//过欠压配置类型


typedef struct {
    struct {
    int      olEnterTime_1s;//当前已进入判定阈值的时间,该值超过olThrEnterTime_1s判定为该级过载
    int      olExitTime_1s;//当前已退出判定阈值的时间,该值超过olThrExitTime_1s判定为脱离该级过载
    uint32_t olKeepTime_1s;//该级过载已持续的时间(保持该级过载不变的情况下).
    uint32_t olTotalTime_1s;//该级过载总工作的时间.
    uint32_t olOnTime_1s;//系统功率级别为该级过载已持续的时间().
    }level[OUVOLTAGE_LEVEL_QTY];
}ouVoltageRealtimeInfoType;



static ouVoltageConfType ouVoltageConfig[OUVOLTAGE_LEVEL_QTY];

static ouVoltageRealtimeInfoType ouVoltageRealtimeInfo[PHASE_QTY];

int ouVoltage_GetVoltageThreshold(void)
//获取3级过/欠压的阈值和判定时间.
{
    int levelIdx=0;
    float value;
    ouVoltageConfType* pVoltageConfig = ouVoltageConfig;
    for(levelIdx=0;levelIdx<OUVOLTAGE_LEVEL_QTY;levelIdx++)
    {
        switch(levelIdx)
        {
            case UNDERVOLTAGE_LEVEL_1:
            {
                FuncInf_GetArmThrshd(FUNCINF_ARM_THR_TYPE_3L_UV_THR,&value);
                pVoltageConfig[levelIdx].olThrEnterVoltage_1v = (int)value;

                FuncInf_GetArmThrshd(FUNCINF_ARM_THR_TYPE_3L_UV_TIME,&value);
                pVoltageConfig[levelIdx].olThrEnterTime_1s    = (int)value;

                pVoltageConfig[levelIdx].olThrExitVoltage_1v  = pVoltageConfig[levelIdx].olThrEnterVoltage_1v;
                pVoltageConfig[levelIdx].olThrExitTime_1s     = 10;
            }break;
            case UNDERVOLTAGE_LEVEL_2:
            {
                FuncInf_GetArmThrshd(FUNCINF_ARM_THR_TYPE_3L_UV_THR,&value);
                pVoltageConfig[levelIdx].olThrEnterVoltage_1v = (int)value;

                FuncInf_GetArmThrshd(FUNCINF_ARM_THR_TYPE_3L_UV_TIME,&value);
                pVoltageConfig[levelIdx].olThrEnterTime_1s    = (int)value;

                pVoltageConfig[levelIdx].olThrExitVoltage_1v  = pVoltageConfig[levelIdx].olThrEnterVoltage_1v;
                pVoltageConfig[levelIdx].olThrExitTime_1s     = pVoltageConfig[levelIdx].olThrEnterTime_1s;
            }break;
            case UNDERVOLTAGE_LEVEL_3:
            {
                FuncInf_GetArmThrshd(FUNCINF_ARM_THR_TYPE_3L_UV_THR,&value);
                pVoltageConfig[levelIdx].olThrEnterVoltage_1v = (int)value;

                FuncInf_GetArmThrshd(FUNCINF_ARM_THR_TYPE_3L_UV_TIME,&value);
                pVoltageConfig[levelIdx].olThrEnterTime_1s    = (int)value;

                pVoltageConfig[levelIdx].olThrExitVoltage_1v  = pVoltageConfig[levelIdx].olThrEnterVoltage_1v;
                pVoltageConfig[levelIdx].olThrExitTime_1s     = pVoltageConfig[levelIdx].olThrEnterTime_1s;
            }break;
            case OVERVOLTAGE_LEVEL_1:
            {
                FuncInf_GetArmThrshd(FUNCINF_ARM_THR_TYPE_3L_OV_THR,&value);
                pVoltageConfig[levelIdx].olThrEnterVoltage_1v = (int)value;

                FuncInf_GetArmThrshd(FUNCINF_ARM_THR_TYPE_3L_OV_TIME,&value);
                pVoltageConfig[levelIdx].olThrEnterTime_1s    = (int)value;

                pVoltageConfig[levelIdx].olThrExitVoltage_1v  = pVoltageConfig[levelIdx].olThrEnterVoltage_1v;
                pVoltageConfig[levelIdx].olThrExitTime_1s     = 10;
            }break;
            case OVERVOLTAGE_LEVEL_2:
            {
                FuncInf_GetArmThrshd(FUNCINF_ARM_THR_TYPE_3L_OV_THR,&value);
                pVoltageConfig[levelIdx].olThrEnterVoltage_1v = (int)value;

                FuncInf_GetArmThrshd(FUNCINF_ARM_THR_TYPE_3L_OV_TIME,&value);
                pVoltageConfig[levelIdx].olThrEnterTime_1s    = (int)value;

                pVoltageConfig[levelIdx].olThrExitVoltage_1v  = pVoltageConfig[levelIdx].olThrEnterVoltage_1v;
                pVoltageConfig[levelIdx].olThrExitTime_1s     = pVoltageConfig[levelIdx].olThrEnterTime_1s;
            }break;
            case OVERVOLTAGE_LEVEL_3:
            {
                FuncInf_GetArmThrshd(FUNCINF_ARM_THR_TYPE_3L_OV_THR,&value);
                pVoltageConfig[levelIdx].olThrEnterVoltage_1v = (int)value;

                FuncInf_GetArmThrshd(FUNCINF_ARM_THR_TYPE_3L_OV_TIME,&value);
                pVoltageConfig[levelIdx].olThrEnterTime_1s    = (int)value;

                pVoltageConfig[levelIdx].olThrExitVoltage_1v  = pVoltageConfig[levelIdx].olThrEnterVoltage_1v;
                pVoltageConfig[levelIdx].olThrExitTime_1s     = pVoltageConfig[levelIdx].olThrEnterTime_1s;
            }break;
        }
    }
    return 0;
}



void OverUnderVoltage_Loop(void* pPara)
//主要用于判别一级过/欠压
{
    int index=0,phaseIdex=0;
    int rtVoltage_1v[PHASE_QTY]={0};/* 交流三相电压 */
    int currVoltage_1v;
    int enterThrVoltage_1v,exitThrVoltage_1v;
    int enterThrTime_1s/*进入该级的判定时间阈值*/,exitThrTime_1s/*退出该级的判定时间阈值*/;
    fpagDataFsm_t fsm;
    funcInfRunMode_t runMode;
    float act_U;
    uint16_t arm3LSwitch;

    const ouVoltageConfType* pOuVoltageConfig = ouVoltageConfig;

    ouVoltageRealtimeInfoType* pOUVoltageRealtimeInfo = ouVoltageRealtimeInfo;

    if(FUNCINF_ERR_NONE == FuncInf_GetFsm(FUNCINF_FSM_TYPE_THIS_TIME,&fsm))
    {
        FuncInf_GetRunMode(NULL,&runMode);

        if((fsm == FUNCINF_FSM_IDLE) || (fsm == FUNCINF_FSM_FAULT) || (fsm == FUNCINF_FSM_STOP))
        //关机后将过压计时时间清零, 故障标志位置0
        {
            for(phaseIdex=0;phaseIdex<PHASE_QTY;phaseIdex++)
            {
                for(index=0;index<OUVOLTAGE_LEVEL_QTY;index++)
                {
                    pOUVoltageRealtimeInfo[phaseIdex].level[index].olKeepTime_1s = 0;
                }
            }

            if((fsm == FUNCINF_FSM_IDLE) || (fsm == FUNCINF_FSM_STOP))
            {
                GlobalVariable_SetUint8(GV_UINT8_3L_OV_A, 0);
                GlobalVariable_SetUint8(GV_UINT8_3L_OV_B, 0);
                GlobalVariable_SetUint8(GV_UINT8_3L_OV_C, 0);
                GlobalVariable_SetUint8(GV_UINT8_3L_UV_A, 0);
                GlobalVariable_SetUint8(GV_UINT8_3L_UV_B, 0);
                GlobalVariable_SetUint8(GV_UINT8_3L_UV_C, 0);
            }
            return;
        }

        if((runMode == FUNCINF_RUN_MODE_VF) && (fsm != FUNCINF_FSM_WORKING))
        {
            return;
        }
    }
    else
    {
        return;
    }

    //ARM三级保护策略使能后才检测过欠压
    if(FUNCINF_ERR_NONE == FuncInf_GetStrategySwitch(FUNCINF_STRTG_SWITCH_TYPE_ARM_3L_PRTCT,&arm3LSwitch))
    {
        if(arm3LSwitch == 0)
        //未使能三级保护, 故障标志位置0
        {
            GlobalVariable_SetUint8(GV_UINT8_3L_OV_A, 0);
            GlobalVariable_SetUint8(GV_UINT8_3L_OV_B, 0);
            GlobalVariable_SetUint8(GV_UINT8_3L_OV_C, 0);
            GlobalVariable_SetUint8(GV_UINT8_3L_UV_A, 0);
            GlobalVariable_SetUint8(GV_UINT8_3L_UV_B, 0);
            GlobalVariable_SetUint8(GV_UINT8_3L_UV_C, 0);
            return;
        }
    }

    FuncInf_GetVoltage(FUNCINF_CUR_TYPE_PHASE_A,&act_U);
    rtVoltage_1v[PHASE_UAB] = (int)act_U;
    FuncInf_GetVoltage(FUNCINF_CUR_TYPE_PHASE_B,&act_U);
    rtVoltage_1v[PHASE_UBC] = (int)act_U;
    FuncInf_GetVoltage(FUNCINF_CUR_TYPE_PHASE_C,&act_U);
    rtVoltage_1v[PHASE_UCA] = (int)act_U;

    if(pPara)
    {
        printf("Module:OverUnderVoltage detect Uab,Ubc,Uca:%d,%d,%d(1v)\n",
            rtVoltage_1v[PHASE_UAB],
            rtVoltage_1v[PHASE_UBC],
            rtVoltage_1v[PHASE_UCA]);
    }

    //三项不平衡检测,FPGA已经做了,这里就不再做了.这里只做过欠压检测

    ouVoltage_GetVoltageThreshold();
    for(phaseIdex=0;phaseIdex<PHASE_QTY;phaseIdex++)
    {
        currVoltage_1v = rtVoltage_1v[phaseIdex];
        for(index=0;index<OUVOLTAGE_LEVEL_QTY;index++)
        {
            //阈值
            enterThrVoltage_1v = pOuVoltageConfig[index].olThrEnterVoltage_1v;
            exitThrVoltage_1v  = pOuVoltageConfig[index].olThrExitVoltage_1v;
    
            //时间阈值
            enterThrTime_1s = pOuVoltageConfig[index].olThrEnterTime_1s;
            exitThrTime_1s = pOuVoltageConfig[index].olThrExitTime_1s;
            
            switch(index)
            {
                case UNDERVOLTAGE_LEVEL_1:
                case UNDERVOLTAGE_LEVEL_2://该级别由FPGA进行判断,ARM这里未配置参数,也会导致判中,我们主动忽略
                case UNDERVOLTAGE_LEVEL_3://该级别由FPGA进行判断,ARM这里未配置参数,也会导致判中,我们主动忽略
                {
                    if(currVoltage_1v < enterThrVoltage_1v)
                    //满足该级进入判定
                    {
                        if(pOUVoltageRealtimeInfo[phaseIdex].level[index].olEnterTime_1s++ >= enterThrTime_1s)
                        {
                            pOUVoltageRealtimeInfo[phaseIdex].level[index].olKeepTime_1s++;//本次该级欠压持续的时间
                            pOUVoltageRealtimeInfo[phaseIdex].level[index].olTotalTime_1s++;//自arm启动以来该级欠压总共的时间
                        }
                    }
                    else
                    {
                        pOUVoltageRealtimeInfo[phaseIdex].level[index].olEnterTime_1s = 0;
                    }
                    
                    if(currVoltage_1v >= exitThrVoltage_1v)
                    //满足该级退出判定
                    {
                        if(pOUVoltageRealtimeInfo[phaseIdex].level[index].olExitTime_1s++ >= exitThrTime_1s)
                        {
                            pOUVoltageRealtimeInfo[phaseIdex].level[index].olKeepTime_1s = 0;
                        }
                    }
                    else
                    {
                        pOUVoltageRealtimeInfo[phaseIdex].level[index].olExitTime_1s = 0;
                    }
                    
                }break;
                case OVERVOLTAGE_LEVEL_1 :
                case OVERVOLTAGE_LEVEL_2 ://该级别由FPGA进行判断,ARM这里未配置参数,也会导致判中,我们主动忽略
                case OVERVOLTAGE_LEVEL_3 ://该级别由FPGA进行判断,ARM这里未配置参数,也会导致判中,我们主动忽略
                {
                    if(currVoltage_1v > enterThrVoltage_1v)
                    //满足该级进入判定
                    {
                        if(pOUVoltageRealtimeInfo[phaseIdex].level[index].olEnterTime_1s++ >= enterThrTime_1s)
                        {
                            pOUVoltageRealtimeInfo[phaseIdex].level[index].olKeepTime_1s++;//本次该级过压持续的时间
                            pOUVoltageRealtimeInfo[phaseIdex].level[index].olTotalTime_1s++;//自arm启动以来该级过压总共的时间
                        }
                    }
                    else
                    {
                        pOUVoltageRealtimeInfo[phaseIdex].level[index].olEnterTime_1s = 0;
                    }
                    
                    if(currVoltage_1v <= exitThrVoltage_1v)
                    //满足该级退出判定
                    {
                        if(pOUVoltageRealtimeInfo[phaseIdex].level[index].olExitTime_1s++ >= exitThrTime_1s)
                        {
                            pOUVoltageRealtimeInfo[phaseIdex].level[index].olKeepTime_1s = 0;
                        }
                    }
                    else
                    {
                        pOUVoltageRealtimeInfo[phaseIdex].level[index].olExitTime_1s = 0;
                    }
                    
                }break;
            }
    
#if 1 //我们只关注1级过欠压(上位机点表定义为3级过欠压),其它级别的由FPGA自己处理
            if(pOUVoltageRealtimeInfo[phaseIdex].level[index].olKeepTime_1s == 1)
            //1级过/欠压
            {
                if((OVERVOLTAGE_LEVEL_1==index))
                {
                    switch(phaseIdex)
                    {
                        case PHASE_UAB:
                        {
                            GlobalVariable_SetUint8(GV_UINT8_3L_OV_A, 1);
                            printf("Module:OVERVOLTAGE happen Uab:%d(1v)\n",rtVoltage_1v[PHASE_UAB]);
                        }break;
                        case PHASE_UBC:
                        {
                            GlobalVariable_SetUint8(GV_UINT8_3L_OV_B, 1);
                            printf("Module:OVERVOLTAGE happen Ubc:%d(1v)\n",rtVoltage_1v[PHASE_UBC]);
                        }break;
                        case PHASE_UCA:
                        {
                            GlobalVariable_SetUint8(GV_UINT8_3L_OV_C, 1);
                            printf("Module:OVERVOLTAGE happen Uca:%d(1v)\n",rtVoltage_1v[PHASE_UCA]);
                        }break;
                    }
                    // FuncInf_TurnOnOff(FUNCINF_OPERATOR_OVER_UNDER_VOL,NULL,FUNCINF_TURN_OFF);
                }
                if((UNDERVOLTAGE_LEVEL_1==index))
                {
                    switch(phaseIdex)
                    {
                        case PHASE_UAB:
                        {
                            GlobalVariable_SetUint8(GV_UINT8_3L_UV_A, 1);
                            printf("Module:UNDERVOLTAGE happen Uab:%d(1v)\n",rtVoltage_1v[PHASE_UAB]);
                        }break;
                        case PHASE_UBC:
                        {
                            GlobalVariable_SetUint8(GV_UINT8_3L_UV_B, 1);
                            printf("Module:UNDERVOLTAGE happen Ubc:%d(1v)\n",rtVoltage_1v[PHASE_UBC]);
                        }break;
                        case PHASE_UCA:
                        {
                            GlobalVariable_SetUint8(GV_UINT8_3L_UV_C, 1);
                            printf("Module:UNDERVOLTAGE happen Uca:%d(1v)\n",rtVoltage_1v[PHASE_UCA]);
                        }break;
                    }
                    // FuncInf_TurnOnOff(FUNCINF_OPERATOR_OVER_UNDER_VOL,NULL,FUNCINF_TURN_OFF);
                }
            }
            else if(pOUVoltageRealtimeInfo[phaseIdex].level[index].olKeepTime_1s == 0)
            //1级过/欠压恢复
            {
                if((OVERVOLTAGE_LEVEL_1==index))
                {
                    switch(phaseIdex)
                    {
                        case PHASE_UAB:
                        {
                            GlobalVariable_SetUint8(GV_UINT8_3L_OV_A, 0);
                        }break;
                        case PHASE_UBC:
                        {
                            GlobalVariable_SetUint8(GV_UINT8_3L_OV_B, 0);
                        }break;
                        case PHASE_UCA:
                        {
                            GlobalVariable_SetUint8(GV_UINT8_3L_OV_C, 0);
                        }break;
                    }
                }
                if((UNDERVOLTAGE_LEVEL_1==index))
                {
                    switch(phaseIdex)
                    {
                        case PHASE_UAB:
                        {
                            GlobalVariable_SetUint8(GV_UINT8_3L_UV_A, 0);
                        }break;
                        case PHASE_UBC:
                        {
                            GlobalVariable_SetUint8(GV_UINT8_3L_UV_B, 0);
                        }break;
                        case PHASE_UCA:
                        {
                            GlobalVariable_SetUint8(GV_UINT8_3L_UV_C, 0);
                        }break;
                    }
                }
            }
#endif
    
        }
    }

}

int OverUnderVoltage_Get(int phaseIdex,int level)
{
    ouVoltageRealtimeInfoType* pOUVoltageRealtimeInfo = ouVoltageRealtimeInfo;
    if(((0<=phaseIdex)&&(phaseIdex<PHASE_QTY))&&
        ((OUVOLTAGE_LEVEL_NONE<level)&&(level<OUVOLTAGE_LEVEL_QTY)))
    {
        return (0 != pOUVoltageRealtimeInfo[phaseIdex].level[level].olKeepTime_1s);
    }
    printf("%s parameter phaseIdx:%d beyond scale[0,3),or level:%d beyond scale(0,7)\n",__FUNCTION__,phaseIdex,level);
    return 0;
}

#endif

